import pandas as pd
import os
from filelock import FileLock
import json
from noflip_web.globals import engine_ins_dc
from tools.methods import safe_to_csv


def split_df_by_symbol(df: pd.DataFrame):
    """
    如果DataFrame中存在'symbol'列，则按此列的值拆分DataFrame。
    否则，返回原始DataFrame。

    :param df: 输入的DataFrame。
    :return: 字典，键为'symbol'的值，值为对应的DataFrame，或者原始DataFrame。
    """

    def drop_repeat_index(df_f):
        """
        移除DataFrame中重复的索引行，但保留每组重复索引中的最后一行。
        """
        return_df = df_f.reset_index().drop_duplicates(subset='datetime', keep='last').set_index('datetime', drop=True)
        return return_df

    if 'symbol' in df.columns:
        # 按"symbol"的值拆分DataFrame
        df_dc = {symbol: drop_repeat_index(sub_df.drop(columns=['symbol'])) for symbol, sub_df in df.groupby('symbol')}
        return df_dc
    else:
        # 如果"symbol"列不存在
        return {"DDQ001": drop_repeat_index(df)}


def read_csv(path) -> pd.DataFrame:
    """仅用于读取时间序列的csv文件，且数据以时间为索引"""
    lock = FileLock(path + ".lock")
    with lock:
        try:
            data = pd.read_csv(path)
        except Exception as e:
            print(e)
            print("使用gbk编码继续尝试。")
            data = pd.read_csv(path, encoding='gbk')

    if "datetime" in data.columns:
        # 将时间作为索引
        data = data.set_index("datetime", drop=True)
        data.index = pd.to_datetime(data.index)
    elif '' in data.columns:
        data = data.set_index('', drop=True)
        data.index = pd.to_datetime(data.index)
        data.index.name = "datetime"
    else:
        pass

    return data


def read_dc_csv(path) -> dict:
    """仅用于读取时间序列的csv文件，且数据以时间为索引"""
    if os.path.exists(path):
        lock = FileLock(path + ".lock")
        with lock:
            data = pd.read_csv(path)
        # 将时间作为索引
        if "datetime" in data.columns:
            data = data.set_index('datetime', drop=True)
        elif '' in data.columns:
            data = data.set_index('', drop=True)
            data.index.name = "datetime"
        elif "Unnamed: 0" in data.columns:
            data = data.set_index("Unnamed: 0", drop=True)
            data.index.name = "datetime"
        else:
            raise ValueError("索引设置异常。")
        temp = str(data.index[0]).isdigit()
        if not temp:
            data.index = pd.to_datetime(data.index)
        else:
            data.index = pd.to_datetime(data.index, format="%Y%m%d")
        data_split = split_df_by_symbol(data)
        return data_split
    else:
        return False


def save_csv(data: pd.DataFrame, path):
    if data is not None:
        data.index.name = "datetime"
        safe_to_csv(data, path)
        info = f"新csv文件生成，路径：{path}。"
    else:
        info = f"数据为None，未能保存。"
    print(info)


def save_dc_csv(data_dc: dict[str, pd.DataFrame], path):
    combined_df = pd.DataFrame()
    for df_name, df in data_dc.items():
        df["symbol"] = df_name
        combined_df = pd.concat([combined_df, df])
    combined_df = combined_df.sort_index()
    if not combined_df.index.name:
        combined_df.index.name = "datetime"
    safe_to_csv(combined_df, path)
    info = f"新csv文件生成，路径：{path}"
    print(info)


def get_model_name_code(model_name=None):
    model_name_code = None
    if model_name is not None:
        for k, v in engine_ins_dc["all_variable"].items():
            if v["lab_var_part2_1"]["title"] == model_name:
                model_name_code = k
                break
    else:
        for k, v in engine_ins_dc["all_variable"].items():
            if v["selected"]:
                model_name_code = k
                break

    if model_name_code is None:
        raise ValueError("model_name_code未找到，逻辑错误。")

    return model_name_code


def delete_model(model_name):
    """删除相应引擎和variable"""
    if len(engine_ins_dc["all_variable"]) == 0 or len(engine_ins_dc["all_variable"]) == 1:
        raise ValueError("当前model的数量为0或1，不支持删除操作。")
    # 根据model_name查找model_name_code
    model_name_code = get_model_name_code(model_name)
    # ！！ 需要注意在删除后不会主动推送新数据到前端，需要在上一级函数中主动调用
    del engine_ins_dc["all_variable"][model_name_code]
    if model_name_code != engine_ins_dc["active_engine"]:
        # 若删除的不是当前活跃的
        new_model_name_code = engine_ins_dc["active_engine"]
        pass
    else:
        # 若删除的是当前活跃的
        # 获取除了被删除model的引擎和variable后，最新的model
        new_model_name_code = list(engine_ins_dc["all_variable"].keys())[-1]

    return new_model_name_code






